package com.gallop.mq.core;

import com.gallop.mq.MQTemplate;
import com.gallop.mq.core.exception.MQException;
import com.gallop.mq.core.template.*;
import com.gallop.mq.core.template.handler.registry.DefaultHandlerRegistry;
import com.gallop.mq.core.template.handler.registry.MessageDeliveryHandlerRegistry;
import com.gallop.mq.core.template.handler.registry.RegistryHolder;

import java.util.function.Supplier;

public enum SupportedType {

    NATS(NatsMQTemplate::new, null),
    KAFKA(KafkaMQTemplate::new),
    RABBIT_MQ(RabbitMQTemplate::new),
    ACTIVE_MQ(ActiveMQTemplate::new),
    ZERO_MQ(NopTemplate::new),
    NOP(NopTemplate::new),
    CUSTOM(() -> {
        throw new MQException("provide your own custom MQTemplateInitializer bean and instantiate your own MQTemplate in `init` method.");
    }, null);

    private final Supplier<? extends MQTemplate> templateSupplier;
    private final Supplier<? extends MessageDeliveryHandlerRegistry> registrySupplier;

    SupportedType(Supplier<? extends MQTemplate> templateSupplier) {
        this(templateSupplier, DefaultHandlerRegistry::new);
    }

    SupportedType(Supplier<? extends MQTemplate> templateSupplier, Supplier<? extends MessageDeliveryHandlerRegistry> registrySupplier) {
        this.templateSupplier = templateSupplier;
        this.registrySupplier = registrySupplier;
    }

    public MQTemplateInitializer getInitializer() {
        return (properties, dispatcher, codec, executorProvider) -> {
            MQTemplate template = templateSupplier.get();
            template.init(properties, dispatcher, codec, executorProvider, supplyRegistry());
            return template;
        };
    }

    private MessageDeliveryHandlerRegistry supplyRegistry() {
        if (this.registrySupplier == null) {
            return null;
        }
        return this.registrySupplier.get();
    }
}
